/**
Company: Sarkar software technologys
WebSite: http://www.sarkar.cn
Author: yeganaaa
Date : 11/3/17
Time: 5:55 PM
 */

package Cn.Sarkar.SimplePipeLineServer.Core.Features.Route

import Cn.Sarkar.Pipeline.Core.PipeLineContext
import Cn.Sarkar.SimplePipeLineServer.Core.Entities.ActionMethod
import Cn.Sarkar.SimplePipeLineServer.Core.Entities.SubjectParameter
import Cn.Sarkar.SimplePipeLineServer.Core.Interfaces.FeatureContext
import Cn.Sarkar.SimplePipeLineServer.Core.Utils.KeyValuePair


data class PathAliasName(var fromThisIndexPath: Int, var aliasName: String)

/*
*Examples
*
* ^/{1}SharedFrom/[0-9]{1,9}/Get$
* matchs
* /SharedFrom/653125/Get
*
* */
class PathSelector<TSubject>(var pathRegex: String, var aliasNames: Array<PathAliasName> = arrayOf(), vararg methods: ActionMethod) : IRouteSelector<SubjectParameter<TSubject>, FeatureContext> {
    var acceptedMethods = methods

    override fun PipeLineContext<SubjectParameter<TSubject>, FeatureContext>.select(): Boolean {
        var retv = featureContext.request.method in acceptedMethods
        retv = retv and pathRegex.toRegex().matches(featureContext.request.path.toString())

        if (retv){
            aliasNames.forEach {
                featureContext.pathParameters.add(KeyValuePair(it.aliasName, featureContext.request.path[it.fromThisIndexPath]))
            }
        }

        return retv
    }

    override fun toString(): String {
        return "$pathRegex:${acceptedMethods.map { it.toString() + ":" }}"
    }

    init {
        if (methods.size == 0) throw Exception("Methods cannot be null")
    }
}

fun <TSubject>get(pathRegex: String, vararg aliasName: PathAliasName) : PathSelector<TSubject> {
    return PathSelector(pathRegex, arrayOf(*aliasName) , ActionMethod.Get)
}

fun <TSubject>post(pathRegex: String, vararg aliasName: PathAliasName) : PathSelector<TSubject> {
    return PathSelector(pathRegex, arrayOf(*aliasName) , ActionMethod.Post)
}

fun <TSubject>put(pathRegex: String, vararg aliasName: PathAliasName) : PathSelector<TSubject> {
    return PathSelector(pathRegex, arrayOf(*aliasName) , ActionMethod.Put)
}

fun <TSubject>delete(pathRegex: String, vararg aliasName: PathAliasName) : PathSelector<TSubject> {
    return PathSelector(pathRegex, arrayOf(*aliasName) , ActionMethod.Delete)
}